package com.hntxk;

import com.hntxk.core.ext.spring.context.ApplicationStartedEventListener;
import com.hntxk.core.util.StringUtil;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.slf4j.MDC;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.retry.annotation.EnableRetry;
import springfox.documentation.oas.annotations.EnableOpenApi;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import java.util.Collections;

/**
 * SpringBoot
 * exclude 去掉数据源和Mybatis的自动配置，因为代码中的这部分是动态初始化的，不去掉的话Spring会自动去再配置一遍
 * ServletComponentScan 激活自定义servlet的使用
 * EnableAspectJAutoProxy 激活AOP反向代理模块
 * EnableRetry Spring Retry功能模块
 *
 * RedisAutoConfiguration和RedisRepositoriesAutoConfiguration 是redis的自动配置类，过滤后可以禁止应用连接redis服务器
 *
 * @author a
 */
@SpringBootApplication(exclude ={
        DataSourceAutoConfiguration.class
        ,MybatisAutoConfiguration.class
        ,XADataSourceAutoConfiguration.class
        ,RedisAutoConfiguration.class
        ,RedisRepositoriesAutoConfiguration.class
})
@ServletComponentScan
@EnableAspectJAutoProxy
@EnableRetry
@EnableOpenApi
public class DiagnoseApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        long start  = System.currentTimeMillis();
        //日志文件目录，启动瞬间使用，后面在ApplicationStartedEventListener中有重新指定目录
        System.setProperty(ApplicationStartedEventListener.KEY_LOGGING_PATH,System.getProperty("java.io.tmpdir"));
        ApplicationStartedEventListener startedEventListener = new ApplicationStartedEventListener();
        SpringApplication app = new SpringApplication(DiagnoseApplication.class);
        app.addListeners(startedEventListener);
        app.run(args);
        long end  = System.currentTimeMillis();
        System.out.println("--------------启动完成,耗时："+(end-start)+"ms---------------");
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(DiagnoseApplication.class);
    }

    /**
     * war包方式运行的配置方法
     *
     */
    @Override
    public void onStartup(ServletContext servletContext)throws ServletException {
        //日志文件存储地址
        String logPath = System.getProperty(ApplicationStartedEventListener.KEY_LOGGING_PATH);
        if (StringUtil.isNull(logPath)){
            logPath = System.getProperty("java.io.tmpdir")+"logs";
        }
        MDC.put(ApplicationStartedEventListener.KEY_LOGGING_PATH, logPath);
        MDC.put("logPath", logPath);
        System.setProperty(ApplicationStartedEventListener.KEY_LOGGING_PATH,logPath);
        //日志等级
        String logLevel = System.getProperty(ApplicationStartedEventListener.KEY_LOGGING_LEVEL);
        if (StringUtil.isNull(logLevel)){
            logLevel = "info";
        }
        MDC.put(ApplicationStartedEventListener.KEY_LOGGING_LEVEL, logLevel);
        MDC.put("logLevel", logLevel);
        System.setProperty(ApplicationStartedEventListener.KEY_LOGGING_LEVEL,logLevel);
        super.onStartup(servletContext);

        //使用代码或使用web.xml配置
        servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
        SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
        sessionCookieConfig.setHttpOnly(true);
    }
}